import numpy as np
import copy, base64
import cv2, imutils
import os
from flask import Flask, request
from imutils.perspective import four_point_transform

app = Flask(__name__)


@app.route('/todo/imgcorrect', methods=['get', 'post'])
def imgcorrect():
    base64Img = request.values['base64Img']
    base64ImgStr = base64.b64decode(base64Img)
    nparr = np.fromstring(base64ImgStr, np.uint8)
    img = cv2.imdecode(nparr, cv2.COLOR_RGB2BGR)

    path = r"C:/python/correct_results"
    if not os.path.exists(path):
        os.makedirs(path)
    cv2.imwrite(path + "/srcImg.jpg", img)
    # cv2.imshow("test1", img)
    # cv2.waitKey(0)
    # cv2.imwrite("D:/opencv/srcImg/result1.jpg", img)
    # img = cv2.imread(r".\data\raw_data\img04.jpg")

    screenCnt, ratio, binImg = preprocess(img)

    shape_ = binImg.shape[:2]

    # raise the top line by 40 pixel
    for j in range(4):
        if screenCnt[j][0][1] < 500:
            screenCnt[j][0][1] = screenCnt[j][0][1] - 45
        else:
            screenCnt[j][0][1] = screenCnt[j][0][1] + 10

        if screenCnt[j][0][0] < shape_[1] * 0.5:
            screenCnt[j][0][0] = screenCnt[j][0][0] - 25
        else:
            screenCnt[j][0][0] = screenCnt[j][0][0] + 25

        if screenCnt[j][0][1] < 0:
            screenCnt[j][0][1] = 0
        if screenCnt[j][0][1] > shape_[0] - 1:
            screenCnt[j][0][1] = shape_[0] - 1
        if screenCnt[j][0][0] < 0:
            screenCnt[j][0][0] = 0
        if screenCnt[j][0][0] > shape_[1] - 1:
            screenCnt[j][0][0] = shape_[1] - 1

    warped = four_point_transform(img, screenCnt.reshape(4, 2) * ratio)
    
    s_warped = warped.shape[0]*warped.shape[1]
    s_raw = shape_[0]*shape_[1]
    
    if 1.0*s_warped/s_raw < 0.7:
        print "CAN'T BE CORRECTED! RETURN ORIGINAL IMG!"
        warped = img

    cv2.imwrite(path + "/resultImg.jpg", warped)
    # cv2.imshow("test2", warped)
    # cv2.waitKey(0)

    # imgData = base64.b64decode(warped)
    # nparr = np.fromstring(imgData, np.uint8)
    # img_np = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
    # resultImg = cv2.imencode('.jpg', warped)[1]
    # base64_data = str(base64.b64encode(resultImg))[2:-1]

    with open(path + "/resultImg.jpg", "rb") as f:
        base64_data = base64.b64encode(f.read())
    return base64_data


def preprocess(img):
    ratio = img.shape[0] / 1000.0
    img = imutils.resize(img, height=1000)
    imgH, imgW = img.shape[:2]  

    grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    binImg = cv2.adaptiveThreshold(grayImg, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 17, 4)
    binImg = cv2.equalizeHist(binImg)
    binImg = cv2.bitwise_not(binImg)
    cv2.imwrite(r"C:/python/correct_results/binImg.jpg", binImg)

    # horizon = copy.deepcopy(binImg)
    # vertical = copy.deepcopy(binImg)
    #
    # scale = 70
    # horizonSize = horizon.shape[1] / scale
    # horizonStr = cv2.getStructuringElement(cv2.MORPH_RECT, (int(horizonSize), 1))
    # horizon = cv2.erode(horizon, horizonStr)
    # horizon = cv2.dilate(horizon, horizonStr)
    # cv2.imwrite(r"D:/python/correct_results/horizon.jpg", horizon)
    #
    # scale = 70
    # verticalSize = vertical.shape[0] / scale
    # verticalStr = cv2.getStructuringElement(cv2.MORPH_RECT, (1, int(verticalSize)))
    # vertical = cv2.erode(vertical, verticalStr)
    # vertical = cv2.dilate(vertical, verticalStr)
    # cv2.imwrite(r"D:/python/correct_results/vertical.jpg", vertical)
    #
    # add = horizon + vertical
    # cv2.imwrite(r"D:/python/correct_results/add.jpg", add)

    cnts, hierarchy = cv2.findContours(binImg.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:20]

    for c in cnts:
        peri = cv2.arcLength(c, True)  # calculate contour circumference
        approx = cv2.approxPolyDP(c, 0.02 * peri, True)

        if len(approx) == 4:
            screenCnt = approx
            break
        else:
            screenCnt = np.array([[[0,0]],[[imgW-1,0]], [[0, imgH-1]], [[imgW-1, imgH-1]] ])
    return screenCnt, ratio, binImg


if __name__ == "__main__":
    app.run(host="127.0.0.1", port="1482")
    # b64Img = imgcorrect()